Skip to content

feat(resilience): add agent immortality foundation [Story 482.1] - #718

Merged
rafaelscosta merged 1 commit into
mainfrom
issue-482-agent-immortality-20260509
May 9, 2026
Merged

feat(resilience): add agent immortality foundation [Story 482.1]#718
rafaelscosta merged 1 commit into
mainfrom
issue-482-agent-immortality-20260509

Conversation

@rafaelscosta

@rafaelscosta rafaelscosta commented May 9, 2026

Copy link
Copy Markdown
Collaborator

Summary\n- Implements Agent Immortality Phase 1 for #482: AutopsyEngine, ReincarnationQueue, StateCommitLog, EvolutionLog and AgentImmortalityProtocol orchestration.\n- Persists compact autopsy reports, queued reincarnation context, delta state commits and evolution events under .aiox/immortality.\n- Adds bounded legacy compression and prevention directives so recovery context does not re-trigger context overflow.\n- Adds optional GotchasMemory integration for fatal failure tracking.\n\n## Triage evidence\n- #482 is the last open issue after #483/#717.\n- Historical PR #576 is closed without merge and exposes no merged commits.\n- Historical PR #590 is closed without merge; its large implementation was reviewed as prior art, not copied wholesale.\n- Current main already has CircuitBreaker and GotchasMemory, but no Autopsy/Reincarnation/State Commit/Evolution runtime.\n\n## Validation\n- npm test -- --runTestsByPath tests/core/resilience/agent-immortality.test.js tests/core/resilience-regressions.test.js\n- npx eslint .aiox-core/core/resilience/agent-immortality.js .aiox-core/core/resilience/index.js tests/core/resilience/agent-immortality.test.js\n- npm run generate:manifest && npm run validate:manifest\n- npm run typecheck\n- npm run lint\n\nRefs #482

Summary by CodeRabbit

  • New Features

    • Exposed a new resilience API for agent "immortality": capture failures, queue recoveries, commit per-agent state, and claim reincarnations.
    • Automatic failure diagnosis, compact reincarnation context, prevention directives, and evolution/pattern logging.
  • Documentation

    • Added user-facing resilience README and epic/story docs describing protocol, acceptance criteria, and usage examples.
  • Tests

    • Added end-to-end and unit tests validating capture/queue/commit/evolution behaviors and persistence robustness.
  • Chores

    • Updated install manifest and package exports to include the resilience surface.

@vercel

vercel Bot commented May 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aiox-core Ready Ready Preview, Comment May 9, 2026 8:02am

Request Review

@github-actions github-actions Bot added type: test Test coverage and quality area: core Core framework (.aios-core/core/) area: docs Documentation (docs/) labels May 9, 2026
@coderabbitai

coderabbitai Bot commented May 9, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

Adds a file-backed Agent Immortality Protocol: constants/schema, safe JSON persistence with file locks and quarantine, normalization and cause diagnosis, legacy/reincarnation-context builders with prevention directives and immunity tokens, per-agent state commits, evolution logging, deterministic reincarnation queue, AutopsyEngine and protocol orchestrator, exports, README/docs, tests, and manifest/registry updates.

Changes

Agent Immortality Protocol Foundation

Layer / File(s) Summary
Schema & Constants
.aiox-core/core/resilience/agent-immortality.js
Defines SCHEMA_VERSION, CauseOfDeath, QueueStatus, Events, default filenames, storage path, sizing and lock parameters.
Filesystem & Serialization
.aiox-core/core/resilience/agent-immortality.js, .aiox-core/install-manifest.yaml
ID generation, ensure-dir, safe JSON-array reads with quarantine, atomic JSON writes, and lock-file coordination with stale-lock cleanup.
Normalization & Failure Diagnosis
.aiox-core/core/resilience/agent-immortality.js
Deep-clone fallback, diagnostic truncation, normalizeError, normalizeState, and regex-based diagnoseCause.
Legacy Summary, Directives & Context
.aiox-core/core/resilience/agent-immortality.js
Builds compact legacy memory tails and omitted counts, suggests pivot actions, generates prevention directives, and composes multiline reincarnation context strings with immunity tokens.
StateCommitLog
.aiox-core/core/resilience/agent-immortality.js
Per-agent delta commits persisted with previousId linkage, schema stamping, timestamps, and list/latest helpers.
EvolutionLog
.aiox-core/core/resilience/agent-immortality.js
Records autopsy-derived evolution events and aggregates failure patterns and toxic-action frequencies.
ReincarnationQueue
.aiox-core/core/resilience/agent-immortality.js
File-backed queue supporting enqueue, deterministic claimNext (QUEUED→CLAIMED), status listing, and corrupt-file quarantine.
Autopsy Engine
.aiox-core/core/resilience/agent-immortality.js
AutopsyEngine.recordDeath normalizes inputs, commits state delta, truncates traces, persists autopsy reports, and exposes context/getters.
Protocol Orchestrator
.aiox-core/core/resilience/agent-immortality.js
AgentImmortalityProtocol.captureFailure() validates inputs, records autopsies, enqueues reincarnation, records evolution events, emits protocol events, supports claiming/committing, and optionally forwards to gotchasMemory.trackError.
Module Exports & Integration
.aiox-core/core/resilience/index.js, .aiox-core/core/index.js, package.json
resilience/index.js re-exports agent-immortality exports; core/index.js exposes module.exports.resilience; package.json adds ./resilience subpath exports.
Resilience README
.aiox-core/core/resilience/README.md
Usage example for AgentImmortalityProtocol, description of recorded artifacts (autopsy report, reincarnation queue item, state delta commit, evolution event), and default storage .aiox/immortality/.
Epic & Story Documentation
docs/stories/epic-482-agent-immortality/*
Epic 482 and Story 482.1 describing Phase 1 scope, acceptance criteria, executor/quality-gate metadata, dev notes, validation commands, file list, and change log.
Test Suite
tests/core/resilience/agent-immortality.test.js
Jest tests covering export verification, autopsy overflow and tool-failure behaviors, immunity tokens, StateCommitLog linkage, ReincarnationQueue determinism and cross-instance idempotency, corruption quarantine, EvolutionLog aggregation, end-to-end orchestration, gotchasMemory forwarding and guarded failures, and input validation.
Install Manifest & Registry
.aiox-core/install-manifest.yaml, .aiox-core/data/entity-registry.yaml
Regenerated manifest (generated_at, file_count 1125→1128), added core/resilience entries with SHA256/size, and updated entity-registry with agent-immortality and resilience-index module entries.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

area: agents, area: devops

Suggested reviewers

  • Pedrovaleriolopez
  • oalanicolas
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and concisely describes the main change: adding the agent immortality foundation (core resilience components) as part of Story 482.1, which aligns with the primary objective of implementing Phase 1 of the Agent Immortality protocol.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-482-agent-immortality-20260509

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 9, 2026

Copy link
Copy Markdown
Contributor

📊 Coverage Report

Coverage report not available

📈 Full coverage report available in Codecov


Generated by PR Automation (Story 6.1)

coderabbitai[bot]
coderabbitai Bot previously requested changes May 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
.aiox-core/core/resilience/agent-immortality.js (3)

119-137: 💤 Low value

Cause-of-death heuristic ordering looks intentional — please confirm.

The order matters because text aggregates name+message+stack and several keywords overlap (e.g., a tool failure whose stack mentions length/tokens would classify as CONTEXT_OVERFLOW; a tool error caused by an HTTP timeout would classify as TOOL_EXECUTION_FAILURE before reaching the API branch because of the tool keyword). The current priority OVERFLOW > RECURSIVE > TOOL > API > UNKNOWN is defensible, but worth a comment to justify the ordering and prevent future "fixes" that reorder it. Minor: the regex \b(...|enoent|...) matches case-insensitively on the lowercased text, so listing enoent/econn works — just noting in case anyone later removes .toLowerCase().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.aiox-core/core/resilience/agent-immortality.js around lines 119 - 137, Add
an explicit comment above the diagnoseCause function explaining that the
heuristic ordering (CONTEXT_OVERFLOW > RECURSIVE_LOOP > TOOL_EXECUTION_FAILURE >
EXTERNAL_API_ERROR > UNKNOWN) is intentional to prioritize
context/token/overflow signals over recursive/tool/api signals because keywords
can overlap in name/message/stack aggregation; also note that text is lowercased
so regex entries like "enoent" and "econn" rely on that and should remain
lowercase if the toLowerCase() call is kept. This will prevent future accidental
reordering and clarify why TOOL and API checks come after overflow/recursive
checks.

52-57: ⚡ Quick win

nextId collisions across processes.

idCounter is module-scoped, so two processes started in the same millisecond will produce identical autopsy-…, state-…, and reincarnation-… ids (both reset idCounter to 0 and share Date.now()). In a single-process workload this is fine, but in this resilience context multiple agents may crash concurrently. Consider crypto.randomUUID() (Node ≥ 14.17) or appending process.pid to make ids globally unique.

♻️ Suggested change
-const fs = require('fs');
-const path = require('path');
-const EventEmitter = require('events');
+const fs = require('fs');
+const path = require('path');
+const crypto = require('crypto');
+const EventEmitter = require('events');
@@
-let idCounter = 0;
-
 function nextId(prefix) {
-  idCounter += 1;
-  return `${prefix}-${Date.now().toString(36)}-${idCounter.toString(36)}`;
+  return `${prefix}-${Date.now().toString(36)}-${crypto.randomUUID().slice(0, 8)}`;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.aiox-core/core/resilience/agent-immortality.js around lines 52 - 57, The
current nextId function uses a module-scoped idCounter and Date.now(), causing
possible collisions across processes (e.g., autopsy-…, state-…, reincarnation-…
ids) when agents start in the same millisecond; update nextId to use a
globally-unique source such as crypto.randomUUID() (Node ≥14.17) instead of
relying solely on idCounter/Date.now(), and if crypto.randomUUID() is
unavailable fall back to appending process.pid and a cryptographic random
component (or use crypto.randomBytes) to the generated ID so each process
produces unique IDs; update references to nextId/idCounter accordingly.

277-277: 💤 Low value

Minor: simplify reverse-then-find / spread-then-pop.

A few spots can drop the array copy:

  • Line 277: [...commits].reverse().find(c => c.agentId === agentId)commits.findLast(c => c.agentId === agentId)
  • Line 299: [...this.list(agentId)].pop() || nullthis.list(agentId).at(-1) || null
  • Line 463: [...this.listReports()].pop() || nullthis.listReports().at(-1) || null

Array.prototype.findLast and at are ES2022, which the codebase targets per AIOX coding standards.

Also applies to: 299-299, 463-463

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.aiox-core/core/resilience/agent-immortality.js at line 277, Replace
reverse-then-find and spread-then-pop patterns with modern ES2022 APIs: for the
variable using commits and agentId (const previous =
[...commits].reverse().find(commit => commit.agentId === agentId)), use
commits.findLast(c => c.agentId === agentId); for the call using
this.list(agentId) ([...this.list(agentId)].pop() || null) use
this.list(agentId).at(-1) || null; and for the call using this.listReports()
([...this.listReports()].pop() || null) use this.listReports().at(-1) || null;
these keep behavior the same while removing unnecessary array copies and relying
on Array.prototype.findLast and Array.prototype.at.
tests/core/resilience/agent-immortality.test.js (1)

44-174: ⚡ Quick win

Solid AC coverage — consider adding a concurrency/persistence-rehydration test.

The suite hits every AC end-to-end and the temp-dir harness is clean. Two optional additions worth considering when the race-condition concern raised on the implementation is addressed:

  1. A test that constructs a fresh AgentImmortalityProtocol instance pointing at the same tempDir and calls claimReincarnation() — verifying the queue actually survives across instance boundaries (the persistence story).
  2. A test that calls enqueue/claimNext interleaved across two protocol instances on the same tempDir, asserting no duplicate claim. This will fail today (see the RMW race comment) and will serve as the regression guard once locking is added.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/core/resilience/agent-immortality.test.js` around lines 44 - 174, Add
two concurrency/persistence tests: (1) create an AgentImmortalityProtocol
pointing at the same tempDir as an existing protocol, call claimReincarnation()
(or claimNext via ReincarnationQueue) and assert a previously enqueued item is
returned — this verifies the queue rehydrates across instances (reference
AgentImmortalityProtocol, ReincarnationQueue, claimReincarnation, claimNext,
enqueue). (2) Spawn two distinct AgentImmortalityProtocol/ReincarnationQueue
instances pointing at the same tempDir, have one enqueue a report and then
concurrently call claimNext from both instances (or interleave
enqueue/claimNext) and assert only one instance receives the claim and the other
gets null — this will detect RMW race duplication and serve as a regression test
for future locking fixes (reference enqueue, claimNext, QueueStatus).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.aiox-core/core/resilience/agent-immortality.js:
- Around line 275-301: The read-modify-write pattern in
StateCommitLog.commitDelta (and related methods list/latest),
ReincarnationQueue.enqueue and ReincarnationQueue.claimNext, and
EvolutionLog.record is racy across processes; wrap each RMW sequence with a
coarse OS-level file lock (e.g., use proper-lockfile or an fs-based sentinel via
fs.openSync(..., 'wx')) so only one process can read, mutate, and write the JSON
atomically; acquire the lock at the start of
commitDelta/enqueue/claimNext/record, re-read the file inside the lock, perform
the mutation (append or state transition and nextId/previousId links), write via
writeJsonAtomic, then release the lock to prevent lost enqueues, double-claims,
and commit forks.
- Around line 529-545: _trackGotcha currently calls gotchasMemory.trackError
directly and can throw, causing captureFailure callers to see failures even
after durable data was written; wrap the call to this.gotchasMemory.trackError
in a try/catch inside _trackGotcha (guarding the call only when
this.gotchasMemory and typeof trackError === 'function') and on error
swallow/log the exception via the existing logger (or a safe fallback) so
failures in the optional gotchas integration do not propagate—target the
_trackGotcha method and the this.gotchasMemory.trackError invocation for this
change.
- Around line 63-69: The readJsonArray function currently calls JSON.parse
directly and can throw a SyntaxError on corrupt files; wrap the parsing (and any
read/trim) in a try/catch inside readJsonArray, catch and log the error with
context (including the filePath and that parsing failed), and return an empty
array on failure so the agent continues operating; ensure the catch only
suppresses JSON/IO parsing errors (rethrow unexpected exceptions if needed) and
keep the function signature and return type unchanged.

In @.aiox-core/core/resilience/README.md:
- Around line 7-29: Replace the local relative
require('./.aiox-core/core/resilience') with the published package path so
consumers can import regardless of working directory; update the import used to
pull AgentImmortalityProtocol and CauseOfDeath to
require('@aiox-squads/core/resilience') (or from the package root
require('@aiox-squads/core') if that re-exports resilience) so the existing
references to AgentImmortalityProtocol and CauseOfDeath continue to work.

---

Nitpick comments:
In @.aiox-core/core/resilience/agent-immortality.js:
- Around line 119-137: Add an explicit comment above the diagnoseCause function
explaining that the heuristic ordering (CONTEXT_OVERFLOW > RECURSIVE_LOOP >
TOOL_EXECUTION_FAILURE > EXTERNAL_API_ERROR > UNKNOWN) is intentional to
prioritize context/token/overflow signals over recursive/tool/api signals
because keywords can overlap in name/message/stack aggregation; also note that
text is lowercased so regex entries like "enoent" and "econn" rely on that and
should remain lowercase if the toLowerCase() call is kept. This will prevent
future accidental reordering and clarify why TOOL and API checks come after
overflow/recursive checks.
- Around line 52-57: The current nextId function uses a module-scoped idCounter
and Date.now(), causing possible collisions across processes (e.g., autopsy-…,
state-…, reincarnation-… ids) when agents start in the same millisecond; update
nextId to use a globally-unique source such as crypto.randomUUID() (Node ≥14.17)
instead of relying solely on idCounter/Date.now(), and if crypto.randomUUID() is
unavailable fall back to appending process.pid and a cryptographic random
component (or use crypto.randomBytes) to the generated ID so each process
produces unique IDs; update references to nextId/idCounter accordingly.
- Line 277: Replace reverse-then-find and spread-then-pop patterns with modern
ES2022 APIs: for the variable using commits and agentId (const previous =
[...commits].reverse().find(commit => commit.agentId === agentId)), use
commits.findLast(c => c.agentId === agentId); for the call using
this.list(agentId) ([...this.list(agentId)].pop() || null) use
this.list(agentId).at(-1) || null; and for the call using this.listReports()
([...this.listReports()].pop() || null) use this.listReports().at(-1) || null;
these keep behavior the same while removing unnecessary array copies and relying
on Array.prototype.findLast and Array.prototype.at.

In `@tests/core/resilience/agent-immortality.test.js`:
- Around line 44-174: Add two concurrency/persistence tests: (1) create an
AgentImmortalityProtocol pointing at the same tempDir as an existing protocol,
call claimReincarnation() (or claimNext via ReincarnationQueue) and assert a
previously enqueued item is returned — this verifies the queue rehydrates across
instances (reference AgentImmortalityProtocol, ReincarnationQueue,
claimReincarnation, claimNext, enqueue). (2) Spawn two distinct
AgentImmortalityProtocol/ReincarnationQueue instances pointing at the same
tempDir, have one enqueue a report and then concurrently call claimNext from
both instances (or interleave enqueue/claimNext) and assert only one instance
receives the claim and the other gets null — this will detect RMW race
duplication and serve as a regression test for future locking fixes (reference
enqueue, claimNext, QueueStatus).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7a55db0e-c8c0-42c0-bbb4-ff44baa614a9

📥 Commits

Reviewing files that changed from the base of the PR and between 96d7f59 and c348985.

📒 Files selected for processing (8)
  • .aiox-core/core/index.js
  • .aiox-core/core/resilience/README.md
  • .aiox-core/core/resilience/agent-immortality.js
  • .aiox-core/core/resilience/index.js
  • .aiox-core/install-manifest.yaml
  • docs/stories/epic-482-agent-immortality/EPIC-482-AGENT-IMMORTALITY.md
  • docs/stories/epic-482-agent-immortality/STORY-482.1-AUTOPSY-REINCARNATION-FOUNDATION.md
  • tests/core/resilience/agent-immortality.test.js

Comment thread .aiox-core/core/resilience/agent-immortality.js
Comment thread .aiox-core/core/resilience/agent-immortality.js
Comment thread .aiox-core/core/resilience/agent-immortality.js
Comment thread .aiox-core/core/resilience/README.md
@rafaelscosta
rafaelscosta force-pushed the issue-482-agent-immortality-20260509 branch from bc7ffe8 to 7c06ac4 Compare May 9, 2026 08:02
@rafaelscosta
rafaelscosta dismissed coderabbitai[bot]’s stale review May 9, 2026 08:11

Dismissed stale CodeRabbit review from commit c348985 after follow-up commit 7c06ac4 addressed the actionable and nitpick findings; required CI checks are green.

@rafaelscosta
rafaelscosta merged commit 9368432 into main May 9, 2026
63 of 69 checks passed
@rafaelscosta
rafaelscosta deleted the issue-482-agent-immortality-20260509 branch May 9, 2026 08:13
@github-actions

github-actions Bot commented May 9, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 5.2.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

tuanmedeiros pushed a commit to tuanmedeiros/aios-core-synkraay that referenced this pull request Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: core Core framework (.aios-core/core/) area: docs Documentation (docs/) released type: test Test coverage and quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant